package com.fingard.dsp.bank.directbank.citicunion01;

import java.util.HashMap;
import java.util.SortedMap;
import java.util.TreeMap;

import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.weixin01.WEIXIN01Base;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqUnifiedOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsUnifiedOrder;
import com.fingard.text.StringHelper;
import com.fingard.text.XmlHelper;
import com.fingard.xml.XmlTextReader;

public class CITICUnionUnifiedOrder extends CITICUnion01Base {
	public RetAtsUnifiedOrder submitUnifiedOrder(ReqUnifiedOrder p_req) {
		RetAtsUnifiedOrder retAts = new RetAtsUnifiedOrder();
		retAts.rdSeq = p_req.rdSeq;

		String submitUrl = "unifiedorder";

		try {
			ActSetItem actItem = getBankConfig().getActSetItemByAny(p_req.ownAct, p_req.merchantId, p_req.appId, "unifiedorder");
			if (actItem != null) {

				SortedMap<String,String> returnMap = new TreeMap<String,String>();

				//	接口类型：QRpay.weixin.native  //pay.weixin.jspay
				String transtype = "";
				if ("SubmitJSAPIOrder".equals(reqHeader.transType)) {
                     transtype = "pay.weixin.jspay";
				} else {
                    //UnionNative01：微信
                    //UnionNative02：支付宝
                    if ("UnionNative02".equals(p_req.reqHeader.commandCode)) {
                        transtype = "pay.alipay.native";
                    } else {
                        transtype = "pay.weixin.native";
                    }
				}
				returnMap.put("service", transtype);
				// 签名类型，取值RSA_1_256，默认RSA_1_256
				returnMap.put("sign_type", "RSA_1_256");
				returnMap.put("version", "2.0");

				returnMap.put("charset", "UTF-8");

				//商户号，由平台分配
				String mch_id = p_req.merchantId;
				if (StringHelper.isNullOrEmpty(mch_id)) {
					mch_id = actItem.merchantId;
				}
				returnMap.put("mch_id", mch_id);

				if ("SubmitJSAPIOrder".equals(reqHeader.transType)) {
					returnMap.put("is_raw", "1");
				}


				//商户订单号	商户系统内部的订单号 ,32个字符内、 可包含字母,确保在商户系统唯一
				returnMap.put("out_trade_no", p_req.rdSeq);
				//商品描述

				if (StringHelper.hasAnyChar(p_req.description)) {
					String body = XmlHelper.encode(p_req.description);
					returnMap.put("body", body);
				}
				//商户附加信息，可做扩展参数
				if (StringHelper.hasAnyChar(p_req.attach)) {
					returnMap.put("attach", p_req.attach);
				}
				//微信公众平台基本配置中的AppID(应用ID)，传入后支付成功可返回对应公众号下的用户openid
				String appid = p_req.appId;
				if (StringHelper.isNullOrEmpty(appid)) {
					appid = actItem.appId;
				}
                if (getBankConfig().getValueAsBool("testMode")) {
                    //测试不传appid
                    appid = "";
                }else {
                    if ("SubmitJSAPIOrder".equals(reqHeader.transType)) {
                        if (StringHelper.isNullOrEmpty(appid)) {
                            retAts.respCode = "-1";
                            retAts.respInfo = "公众号支付，AppID(应用ID)不可为空";
                            return retAts;
                        }
                    }
                }

				if (!"UnionNative02".equals(p_req.reqHeader.commandCode)) {
					returnMap.put("sub_appid", appid);
				}

				if ("SubmitJSAPIOrder".equals(reqHeader.transType)) {
					if (StringHelper.hasAnyChar(p_req.openid) || getBankConfig().getValueAsBool("testMode")) {
                        if (getBankConfig().getValueAsBool("testMode")) {
                            p_req.openid = "";
                        }
						returnMap.put("sub_openid", p_req.openid);
					} else {
						if (StringHelper.isNullOrEmpty(p_req.code)) {
							retAts.respCode = "-1";
							retAts.respInfo = "Code和Openid不能同时为空";
							return retAts;
						} else {
							if (StringHelper.isNullOrEmpty(actItem.appSecret)) {
								retAts.respCode = "-1";
								retAts.respInfo = "未配置公众号的appsecret";
								return retAts;
							} else {
								WEIXIN01Base wxbase = new WEIXIN01Base();
								wxbase.bankFront = this.bankFront;
								wxbase.sbLog = this.sbLog;
								wxbase.reqHeader = this.reqHeader;
								//通过code获取openid
								HashMap<String, String> hashOpenid = wxbase.getOpenid(appid, actItem.appSecret, p_req.code);
								if ("0".equals(hashOpenid.get("RespCode"))) {
									if (hashOpenid.containsKey("openid")) {
										returnMap.put("openid", hashOpenid.get("openid"));
									} else {
										retAts.respCode = "-1";
										retAts.payInfoCode = FailCode.E9981;

										String errcode = "";
										if (hashOpenid.containsKey("errcode")) {
											errcode = hashOpenid.get("errcode");
										}

										String errmsg = "";
										if (hashOpenid.containsKey("errmsg")) {
											errmsg = hashOpenid.get("errmsg");
										}

										retAts.respInfo = StringHelper.joinNotEmpty("-", errcode, errmsg);
										retAts.transState = PaymentState.FAIL_Payment;

										return retAts;
									}
								} else {
									retAts.respCode = "-1";
									retAts.respInfo = hashOpenid.get("RespInfo");

									return retAts;
								}
							}
						}
					}

				}
				//	总金额，以分为单位，不允许包含任何字、符号
				if (StringHelper.hasAnyChar(p_req.amount)) {
					String total_fee = StringHelper.amountMultiply100(p_req.amount);
					returnMap.put("total_fee", total_fee);
				}
				//订单生成的机器 IP
				returnMap.put("mch_create_ip", actItem.createIP);
				//接收平台通知的URL，需给绝对路径，255字符内格式如:http://wap.tenpay.com/tenpay.asp，确保平台能通过互联网访问该地址
				String notify_url = actItem.notifyURL;

				if(StringHelper.isNullOrEmpty(notify_url)){
					notify_url = bankFront.getUrl("unifiedorderNotify");
				}

				if (StringHelper.hasAnyChar(notify_url)) {
					returnMap.put("notify_url", notify_url);
				}else {
					retAts.respCode = "-1";
					retAts.respInfo = "通知地址notify_url未配置，请检查对应config.xml文件";
					return retAts;
				}
				//订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器。注：订单生成时间与超时时间需要同时传入才会生效。
				if (StringHelper.hasAnyChar(p_req.timeStart)) {
					returnMap.put("time_start", p_req.timeStart);
				}
				//	订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自商户服务器。注：订单生成时间与超时时间需要同时传入才会生效。
				if (StringHelper.hasAnyChar(p_req.timeExpire)) {
					returnMap.put("time_expire", p_req.timeExpire);
				}
				//	预留字段此 id 为静态可打印的二维码中包含的商品 ID，商户自行维护。
				if (StringHelper.hasAnyChar(p_req.productId)) {
					returnMap.put("product_id", p_req.productId);
				}
				//随机字符串，不长于 32 位
				String nonce_str = get_nonce_str();
				returnMap.put("nonce_str", nonce_str);

				String limitPay = "";
				if (StringHelper.hasAnyChar(getBankConfig().getValueAsString("limitPay"))) {
					limitPay = getBankConfig().getValueAsString("limitPay");
					if (!"no_credit".equals(limitPay)) {
						limitPay = "0";
					}
					//限定用户使用时能否使用信用卡，值为1，禁用信用卡；值为0或者不传此参数则不禁用
					if (StringHelper.hasAnyChar(limitPay)) {
						returnMap.put("limit_credit_pay", limitPay);
					}
				}
				returnMap.put("sign", msgSign(returnMap, actItem.ownKeyStorePath));
				// 发送银行并获取返回
				String[] tmpStrRet = sendToBank(parseXML(returnMap), submitUrl);// 发送
				if (tmpStrRet[0].length() == 0) {
					StringBuilder tmpSbMsg = new StringBuilder();
					XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1],	tmpSbMsg);
					if (tmpBkReader != null) {
						String return_code = tmpBkReader.getFirstText("/xml/status");
						String return_msg = tmpBkReader.getFirstText("/xml/message");
						// prepay_id
						if (return_code != null && "0".equals(return_code)) {
							String result_code = tmpBkReader.getFirstText("/xml/result_code");
							if (result_code != null	&& "0".equals(result_code)) {
								boolean verifyResult = this.verifySign(tmpStrRet[1], actItem.oppCertFilePath, tmpSbMsg);
								if(verifyResult){
									retAts.respCode = "0";
									retAts.transState = "SUCCESS";
									if("SubmitQROrder".equals(p_req.reqHeader.transType)){
										retAts.qrType = "";
										retAts.qrInfo = tmpBkReader.getFirstText("/xml/code_url");
										retAts.qrImgUrl = tmpBkReader.getFirstText("/xml/code_img_url");
									}else if("SubmitJSAPIOrder".equals(p_req.reqHeader.transType)){
										retAts.customHashMap = new HashMap<String,String>();
										String pay_info = StringHelper.trimEnd(tmpBkReader.getFirstText("/xml/pay_info"),"}");
										String[] jsonValues = pay_info.split(",");
										for(int i=0;i<jsonValues.length;i++){
											String[] keyValue = jsonValues[i].split(":");
											if(keyValue.length == 2){
												if(keyValue[0].indexOf("appId")>=0){
													retAts.customHashMap.put("appId", keyValue[1].trim().replace("\"", ""));
												}
												else if(keyValue[0].indexOf("timeStamp")>=0){
													retAts.customHashMap.put("timeStamp", keyValue[1].trim().replace("\"", ""));
												}
												else if(keyValue[0].indexOf("signType")>=0){
													retAts.customHashMap.put("signType", keyValue[1].trim().replace("\"", ""));
												}
												else if(keyValue[0].indexOf("package")>=0){
													retAts.customHashMap.put("package", keyValue[1].trim().replace("\"", ""));
												}
												else if(keyValue[0].indexOf("nonceStr")>=0){
													retAts.customHashMap.put("nonceStr", keyValue[1].trim().replace("\"", ""));
												}
												else if(keyValue[0].indexOf("paySign")>=0){
													retAts.customHashMap.put("paySign", keyValue[1].trim().replace("\"", ""));
												}
											}
										}
									}
								} else {
									retAts.respCode = "-1";
									retAts.respInfo = "验签失败";
								}
							} else {
								retAts.respCode = "-1";
								retAts.payInfoCode = tmpBkReader.getFirstText("/xml/err_code");
								retAts.respInfo = tmpBkReader.getFirstText("/xml/err_msg");
							}
						} else {
							retAts.respCode = "-1";
							retAts.transState = return_code;
							retAts.respInfo = return_msg;
						}
					} else {
						retAts.respCode = "-1";
						retAts.respInfo = tmpSbMsg.toString();
					}
				} else {
					retAts.respCode = "-1";
					retAts.respInfo = tmpStrRet[1];
				}
			} else {
				retAts.respCode = "0";
				retAts.respInfo = "未找到账号[" + p_req.ownAct + "]商户配置信息";
				retAts.transState = PaymentState.FAIL;
				retAts.payInfoCode = FailCode.E9981;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.respCode = "-1";
			retAts.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		return retAts;
	}

	public RetAtsQueryOrder queryUnifiedOrder(ReqQueryOrder p_req) {
		RetAtsQueryOrder retAts = new RetAtsQueryOrder();
		retAts.rdSeq = p_req.rdSeq;

		try {
			ActSetItem actItem = this.getBankConfig().getActSetItemByAny(p_req.ownAct, p_req.merchantId, p_req.appId, "unifiedorder");
			if (actItem != null) {
				SortedMap<String,String> returnMap = new TreeMap<String,String>();
				//	接口类型：unified.trade.query
				returnMap.put("service", "unified.trade.query");

				//签名类型，取值RSA_1_256，默认RSA_1_256
				returnMap.put("sign_type", "RSA_1_256");


				String mch_id = p_req.merchantId;
				if (StringHelper.isNullOrEmpty(mch_id)) {
					mch_id = actItem.merchantId;
				}
				returnMap.put("mch_id", mch_id);
				//请求流水号
				returnMap.put("out_trade_no", p_req.rdSeq);

				String nonce_str = get_nonce_str();
				returnMap.put("nonce_str", nonce_str);
				returnMap.put("sign", msgSign(returnMap, actItem.ownKeyStorePath));
				// 发送银行并获取返回
                String xml = parseXML(returnMap);
				String[] tmpStrRet = sendToBank(xml, "orderquery");

				// 解析银行返回
				if (tmpStrRet[0].length() == 0) {
					StringBuilder tmpSbMsg = new StringBuilder();
					XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1],	tmpSbMsg);

					if (tmpBkReader != null) {
						String return_code = tmpBkReader.getFirstText("/xml/status");
						String return_msg = tmpBkReader.getFirstText("/xml/message");
						if (return_code != null && "0".equals(return_code)) {
							boolean verifyResult = this.verifySign(tmpStrRet[1], actItem.oppCertFilePath, tmpSbMsg);
							if (verifyResult) {

								String result_code = tmpBkReader.getFirstText("/xml/result_code");
								String err_code = tmpBkReader.getFirstText("/xml/err_code");
								String err_msg = tmpBkReader.getFirstText("/xml/err_msg");
								String trade_state = tmpBkReader.getFirstText("/xml/trade_state");
								//SUCCESS―支付成功
								//REFUND―转入退款
								//NOTPAY―未支付
								//CLOSED―已关闭
								//PAYERROR―支付失败(其他原因，如银行返回失败)
								retAts.respCode = "0";
								retAts.transState = StringHelper.joinNotEmpty("+", result_code, err_code, trade_state);


								String out_trade_no = tmpBkReader.getFirstText("/xml/out_trade_no");
								if (StringHelper.hasAnyChar(out_trade_no)) {
									if (!out_trade_no.equals(p_req.rdSeq)) {
										retAts.respCode = "-1";
										retAts.respInfo = "请求流水号" + p_req.rdSeq + "与响应流水号" + out_trade_no + "不一致";
										return retAts;
									}
								}

								retAts.respInfo = err_msg;

								if(StringHelper.hasAnyChar(err_code)){
									retAts.payInfoCode = err_code;
								}else{
									retAts.payInfoCode = trade_state;
								}
								if(retAts.payInfoCode == null){
									retAts.payInfoCode = "";
								}
								if(retAts.respInfo == null){
									retAts.respInfo = "";
								}
								retAts.oppBank = tmpBkReader.getFirstText("/xml/bank_type");
								retAts.outTransID = tmpBkReader.getFirstText("/xml/transaction_id");
								retAts.openId = tmpBkReader.getFirstText("/xml/openid");
								retAts.oppAct = tmpBkReader.getFirstText("/xml/buyer_logon_id");

							} else {
								retAts.respCode = "-1";
								retAts.respInfo = tmpSbMsg.toString();
							}
						} else {
							retAts.respCode = "-1";
							retAts.respInfo = return_msg;
						}
					} else {
						retAts.respCode = "-1";
						retAts.respInfo = tmpSbMsg.toString();
					}
				} else {
					retAts.respCode = "-1";
					retAts.respInfo = tmpStrRet[1];
				}
			} else {
				retAts.respCode = "-1";
				retAts.respInfo = "未找到账号[" + p_req.ownAct + "]商户配置信息";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.respCode = "-1";
			retAts.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		return retAts;
	}
}
